home *** CD-ROM | disk | FTP | other *** search
- #include "ram:filezap/filezap_protos.h"
-
- /* FileZAP.c : (c) 1986 John Hodgson
-
- FileZAP provides a disk-based file zap utility as popularized
- on TRS systems. Although tested, the author cannot be held liable
- for incidental or consequential damage incurred through the use
- of this program.
-
- Special attention was paid to correct and proper EOF handling;
- please notify the author of any discrepancies (cursor movement
- errors, file growth and/or shrinkage)
-
- Note : Although the physical length of Amiga sectors is just short
- of 512 bytes, 256 byte records are the longest ones that can be
- displayed nicely on a 80x24 screen with all pertinent information.
-
- Have fun! Let's help make this world free from protected disks!
-
- John Hodgson
- P.O. Box 1643
- Pebble Beach, Ca. 93953
-
- Rev 2.2 : Certain portability problems resolved for Aztec "C"
- */
-
- #define AZTEC /* Omit if Lattice */
-
- #ifdef AZTEC
- #include <ctype.h> /* not in lib like Lattice */
- #include <fcntl.h>
- #else /* Lattice? */
- #include <lattice/fcntl.h>
- #endif
-
- #include <exec/types.h>
- #include <intuition/intuition.h>
-
- #define CR 13
- #define EOF 0
- #define ERROR -1
- #define HEX 0
- #define ASC 1
-
- #define IREV 29L /* Intuition rev */
- struct IntuitionBase *IntuitionBase;
-
- /* record buffer physical cursor position (0-15 rows x 0-15 cols) */
- int phycurx=0,phycury=0;
-
- /* physical x-position to video x-cursor map table */
- int posconv[16]={ 6,8,10,12,15,17,19,21,24,26,28,30,33,35,37,39 };
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
- unsigned char inkey,prevchar,secbuf[256],strbuf[80],hexbuf[2];
- int rdfp,wtfp,status,lastrec,curec,shiftnum,len,eof,col;
- long lseek();
- struct IntuitionBase *OpenLibrary();
-
- IntuitionBase=OpenLibrary("intuition.library",IREV);
- if (IntuitionBase==NULL) {
- printf("Error opening Intuition. Exiting...\n");
- exit(0); /* used by DisplayBeep() */
- }
-
- if (argc!=2) { printf("Usage : filezap file\n"); exit(0); }
- if ((rdfp=open(argv[1],O_RDWR))==ERROR) {
- printf("Error opening file %s. Exiting...\n",argv[1]);
- exit(0);
- }
-
- if ((wtfp=open("raw:0/0/640/200/FileZap 2.2 (c) 1986 John Hodgson",O_RDWR))
- ==ERROR) {
- printf("Error opening window. Exiting...\n");
- close(rdfp,&secbuf[0]);
- exit(0);
- }
-
- curec=1; shiftnum=0;
- lastrec=(lseek(rdfp,-1L,2)/256)+1; /* compute last record #, 1..n */
-
- /* compute EOF remainder by reading from last record */
- lseek(rdfp,(long)((lastrec-1)*256),0); eof=read(rdfp,&secbuf[0],256);
-
- /* All data gathered, read 1st record */
- lseek(rdfp,0L,0); status=read(rdfp,&secbuf[0],256);
-
- for (col=0;col<=0xf0;col+=0x10) {
- hexconv(&hexbuf[0],col);
- write(wtfp,&hexbuf[0],2);
- write(wtfp," : \n",4);
- }
-
- prstr(wtfp,62,4,"File : "); write(wtfp,argv[1],strlen(argv[1]));
-
- len=sprintf(&strbuf[0],"EOF : %d",eof);
- prstr(wtfp,62,5,&strbuf[0]);
-
- prstr(wtfp,62,4,"File : "); write(wtfp,argv[1],strlen(argv[1]));
- prstr(wtfp,8,18,"COMMANDS : S) Starting record E) Ending record");
- prstr(wtfp,8,19," F) Forward record B) Backward record");
- prstr(wtfp,8,20," U) Update record R) Recover record");
- prstr(wtfp,8,21," <SPACE> : enter HEX modify * : enter ASCII modify");
- prstr(wtfp,8,23," <n>CR : goto record n ^C : exit program");
-
- display_record(wtfp,&secbuf[0],curec,lastrec,status);
- movecur(wtfp,&secbuf[0],0,0,status); /* display initial cursor */
- prevchar='\0'; /* zero previous char (used for escape checks) */
-
- do {
- read(wtfp,&inkey,1); /* synchronous kybd scan */
-
- if (prevchar==0x9b) { /* Give 2-byte CSI sequences priority (arrows) */
- prevchar='\0';
- switch(inkey) {
- case 'A':
- movecur(wtfp,&secbuf[0],0,-1,status);
- break;
- case 'B':
- movecur(wtfp,&secbuf[0],0,1,status);
- break;
- case 'C':
- movecur(wtfp,&secbuf[0],1,0,status);
- break;
- case 'D':
- movecur(wtfp,&secbuf[0],-1,0,status);
- break;
- }
- continue; /* no point in further tests, restart */
- }
-
- inkey=toupper(inkey); /* force UC for testing */
-
- /* "Goto" record handling - buffer all digits into a shift
- register until too large, or non-digit pressed */
-
- if (isdigit(inkey)) shiftnum=shiftnum*10+inkey-'0';
- else
- if (inkey!=CR) shiftnum=0;
- if (shiftnum>lastrec) shiftnum=0;
-
- if ((inkey==13) && (shiftnum>0)) { /* Goto */
- lseek(rdfp,(long)(256*(shiftnum-1)),0);
- status=read(rdfp,&secbuf[0],256);
- curec=shiftnum; shiftnum=0;
- display_record(wtfp,&secbuf[0],curec,lastrec,status);
- phycurx=phycury=0; movecur(wtfp,&secbuf[0],0,0,status);
- }
-
- if ((inkey=='F') && (curec<lastrec)) { /* Forward record */
- status=read(rdfp,&secbuf[0],256);
- ++curec;
- display_record(wtfp,&secbuf[0],curec,lastrec,status);
- phycurx=phycury=0;movecur(wtfp,&secbuf[0],0,0,status);
- }
- if ((inkey=='B') && (curec>1)) { /* Backward record */
- --curec;
- lseek(rdfp,(long)((curec-1)*256),0);
- status=read(rdfp,&secbuf[0],256);
- display_record(wtfp,&secbuf[0],curec,lastrec,status);
- phycurx=phycury=0;movecur(wtfp,&secbuf[0],0,0,status);
- }
- switch(inkey) {
- case 'R': /* Restore (unmodified) record */
- lseek(rdfp,(long)((curec-1)*256),0);
- status=read(rdfp,&secbuf[0],256);
- display_record(wtfp,&secbuf[0],curec,lastrec,status);
- phycurx=phycury=0;movecur(wtfp,&secbuf[0],0,0,status);
- break;
- case 'S': /* Rewind */
- curec=1;
- lseek(rdfp,0L,0);
- status=read(rdfp,&secbuf[0],256);
- display_record(wtfp,&secbuf[0],curec,lastrec,status);
- phycurx=phycury=0;movecur(wtfp,&secbuf[0],0,0,eof);
- break;
- case 'U': /* Update (save modified) record */
- lseek(rdfp,(long)-status,1);
- write(rdfp,&secbuf[0],status);
- DisplayBeep(NULL);
- break;
- case 'E': /* skip to Ending record */
- curec=lastrec;
- lseek(rdfp,(long)(curec-1)*256,0);
- status=read(rdfp,&secbuf[0],256);
- display_record(wtfp,&secbuf[0],curec,lastrec,status);
- phycurx=phycury=0;movecur(wtfp,&secbuf[0],0,0,status);
- break;
- case ' ': /* Enter hex-modify mode */
- edit_window(wtfp,&secbuf[0],status,HEX);
- break;
- case '*': /* Enter ascii-modify mode */
- edit_window(wtfp,&secbuf[0],status,ASC);
- }
- prevchar=inkey; /* update previous char for CSI sequence checks */
- }
- while (inkey!=3); /* loop until CTRL-C */
-
- close(rdfp); close(wtfp); exit(0); /* cleanup & exit */
- }
-
- display_record(fp,secbuf,cursec,finsec,eof)
- int fp,cursec,finsec,eof;
- char secbuf[16][16];
-
- {
- int row,col,len,i;
- char strbuf[100],*kludge;
-
- /* kludge maps 2-d array to 1-d so we can more easily
- fill incomplete records w/dummy chars past EOF */
-
- kludge=&secbuf[0][0];
- for (i=256;i>eof;--i) kludge[i-1]='#';
-
- /* EOL's included below to erase old values */
- len=sprintf(&strbuf[0],"\x9bKCur rec : %d",cursec);
- prstr(fp,62,1,&strbuf[0]);
- len=sprintf(&strbuf[0],"\x9bKEnd rec : %d",finsec);
- prstr(fp,62,2,&strbuf[0]);
-
- /* record display core routine : Due to the slowness of the
- console file drivers, display is line buffered for speed. */
-
- for (row=0;row<=15;row++) {
- locate(fp,6,row+1); i=0;
- for (col=0;col<=15;col++) {
- hexconv(&strbuf[i],secbuf[row][col]); i+=2;
- if (((col+1)%4)==0) strbuf[i++]=' ';
- }
- strbuf[i++]=':'; strbuf[i++]=' ';
- for (col=0;col<=15;col++) strbuf[i++]=valid_display(secbuf[row][col]);
-
- strbuf[i]='\0'; write(fp,&strbuf[0],strlen(&strbuf[0]));
- }
- }
-
- locate(fp,x,y) /* move cursor to x,y */
- int fp,x,y;
- {
- char decimal[6];
- int length;
-
- /* complete escape sequence for cursor pos is :
- <CSI><row><;><col><H> where CSI is 9BH. */
-
- write(fp,"\x9b",1);
- sprintf(&decimal[0],"%d",y); length=strlen(&decimal[0]);
- /* length=stci_d(&decimal[0],y,sizeof(decimal)); */
- write(fp,&decimal[0],length);
- write(fp,";",1);
- sprintf(&decimal[0],"%d",x); length=strlen(&decimal[0]);
- /* length=stci_d(&decimal[0],x,sizeof(decimal)); */
- write(fp,&decimal[0],length);
- write(fp,"H",1);
- }
-
- hexconv(result,byte) /* byte to 2 ASCII hex digits */
- unsigned char result[2],byte;
- {
- result[0]=(byte>>4);
- result[1]=(byte & 0xf);
- if (result[0]<10) result[0]|=0x30; else result[0]+=55;
- if (result[1]<10) result[1]|=0x30; else result[1]+=55;
- }
-
- prstr(wtfp,posx,posy,string) /* "Print-At" routine */
- int wtfp,posx,posy;
- char *string;
- {
- locate(wtfp,posx,posy);
- write(wtfp,string,strlen(string));
- }
-
- movecur(wtfp,secbuf,deltax,deltay,eof) /* move cursor & update display */
- int wtfp,deltax,deltay,eof;
- char secbuf[16][16];
- {
- char hexbuf[2];
-
- /* update ASCII side */
- hexbuf[0]=valid_display(secbuf[phycury][phycurx]); hexbuf[1]='\0';
- prstr(wtfp,phycurx+44,phycury+1,&hexbuf[0]);
-
- /* disallow cursor movement past EOF */
-
- if (fixpos(wtfp,eof,deltax,deltay)) return(0);
-
- hexconv(&hexbuf[0],(phycury*0x10)+phycurx); /* update HEX side */
-
- prstr(wtfp,62,9,"Loc : "); write(wtfp,&hexbuf[0],2);
-
- locate(wtfp,phycurx+44,phycury+1); /* update ASCII cursor */
- write(wtfp,"*",1);
-
- locate(wtfp,posconv[phycurx],phycury+1); /* update HEX ("real") cursor */
- }
- edit_window(wtfp,secbuf,eof,hex) /* record edit routine */
- int wtfp,eof,hex;
- char secbuf[16][16];
- {
- char ascii,lsb,msb,hexbuf[2];
- int status=NULL,tempx;
-
- if (hex==HEX) prstr(wtfp,62,11,"\x9bKModify : HEX");
- else prstr(wtfp,62,11,"\x9bKModify : ASCII");
-
- prstr(wtfp,62,12,"<ESC> to exit");
-
- do {
-
- locate(wtfp,posconv[phycurx],phycury+1); /* cursor over hex digits */
- write(wtfp," ",2); /* erase previous entry */
- locate(wtfp,posconv[phycurx],phycury+1); /* restore cursor */
-
- if (hex==HEX) { /* hex-modify : Actually, any invalid char exits */
-
- if ((msb=hexfetch(wtfp))==FALSE) { status=1; goto exit; }
- write(wtfp,&msb,1); /* print msb */
-
- if ((lsb=hexfetch(wtfp))==FALSE) { status=1; goto exit; }
- write(wtfp,&lsb,1); /* print lsb */
-
- if (msb>'9') msb-=55; else msb-='0'; /* hex to binary */
- if (lsb>'9') lsb-=55; else lsb-='0';
- secbuf[phycury][phycurx]=(msb<<4)+lsb; /* update buffer */
- }
- else { /* ASCII-modify */
-
- read(wtfp,&ascii,1); /* fetch ASCII char from user */
- if (ascii==0x1b) { status=1; goto exit; }/* exit on <ESC> */
- secbuf[phycury][phycurx]=ascii; /* update buffer */
- }
- exit:
- locate(wtfp,posconv[phycurx],phycury+1); /* restore cursor */
- hexconv(&hexbuf[0],secbuf[phycury][phycurx]);
- write(wtfp,&hexbuf[0],2); /* rewrite old value in case cancelled */
-
- movecur(wtfp,&secbuf[0],0,0,eof); /* update ASCII side */
- if (status==1) break; /* don't move cursor if <ESC> */
-
- tempx=phycurx; /* save previous x-coord */
- movecur(wtfp,&secbuf[0],1,0,eof); /* move to next digit */
- if (tempx==phycurx) status=1; /* cancel modify if blocked */
- }
- while (status==NULL); /* edit until exit */
-
- prstr(wtfp,62,11,"\x9bK"); /* erase info msgs */
- prstr(wtfp,62,12,"\x9bK");
- locate(wtfp,posconv[phycurx],phycury+1); /* restore cursor B4 exit */
- }
-
- hexfetch(wtfp) /* Fetch valid ascii HEX sequence from user */
- int wtfp;
- {
- unsigned char nybble;
-
- for (;;) {
- read(wtfp,&nybble,1);
- if (nybble==0x1b) return(FALSE);
- if (!isalnum(nybble)) continue;
- nybble=toupper(nybble);
- if (nybble>'F') continue;
- return (int)nybble;
- }
- }
-
- fixpos(wtfp,eof,deltax,deltay) /* cursor bounds check routine */
- int wtfp,eof,deltax,deltay;
- {
- int tempx,tempy;
-
- tempx=phycurx+deltax; tempy=phycury+deltay;
-
- if (tempx>15) { tempy++; tempx=0; } /* cursor screen-wrap code */
- if (tempy>15) tempy=0;
- if (tempx<0) { tempx=15; tempy--; }
- if (tempy<0) tempy=15;
-
- if ((((tempy)*16) + (tempx)) > eof-1) { /* cleanup & exit if past EOF */
- locate(wtfp,phycurx+44,phycury+1);
- write(wtfp,"*",1); /* redraw ASCII cursor */
- locate(wtfp,posconv[phycurx],phycury+1); /* redraw HEX cursor */
- DisplayBeep(NULL); /* Flash user so he wakes up */
- return(TRUE); /* and exit */
- }
- phycurx=tempx; phycury=tempy; /* Otherwise, update global cursor */
- return(FALSE);
- }
-
- valid_display(byte) /* return filtered ASCII char */
- char byte;
-
- /* Filter all CTRL & CSI chars which could mess things up */
- {
- if ((byte>31) && (byte!=0x9b)) return(int)byte;
- else return(int)'.';
- }
-